#pragma once
#include <iostream>
#include <mutex>
#include <assert.h>

namespace VirtualR {
typedef struct Node_s Node_t;
struct Node_s { 
  Node_s(std::string key, std::string value, uint32_t height) : key_(key), value_(value), height_(height) {
    prev = (Node_t **)malloc(sizeof(Node_t) * height_);
    next = (Node_t **)malloc(sizeof(Node_t) * height_);
  }

  Node_t **prev;
  Node_t **next;
  std::string key_;
  std::string value_;
  uint32_t height_;
};

class SkipList {
 public:
  SkipList();
  ~SkipList();
  bool get(std::string key, std::string &value);
  bool del(std::string key);
  bool put(std::string key, std::string value);
  uint64_t space();
  uint64_t get_entry_size() {
    return entry_;
  }

  class Iterator {
   public:
    Iterator(SkipList *skip_list, Node_t *node) : skip_list_(skip_list), node_(node) {};
    bool has_next();
    bool valid();
    void next();
    void prev();
    std::string key();
    std::string value();

   private:
    const SkipList *skip_list_;
    Node_t *node_;
  };
  Iterator *iterator();

 private:
  Node_t *find_lower_or_equal_node(std::string key, Node_t **prev);
  void get_random_height(uint32_t &height);

  std::mutex mtx_;
  uint32_t max_height_;
  Node_t *head;
  uint64_t entry_{0};
  uint64_t total_size_{0};
};
} // namespace VirtualR